﻿#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace JH
{
    /// <summary>
    /// 收集并复制预制体资源
    /// </summary>
    public static class CollectAndCopyAsset
    {
        [MenuItem("Assets/收集并复制预制体资源")]
        private static void CollectAndCopyAssetMethod()
        {
            var selection = Selection.objects;
            foreach (Object each in selection)
            {
                CollectAndCopyAssetSingle(each);
            }
        }

        private static void CollectAndCopyAssetSingle(Object each)
        {
            if (each is GameObject go)
            {
                // 收集依赖资产
                var dependencies = EditorUtility.CollectDependencies(new Object[] { go });

                // 处理依赖资产
                DealDependencies(go, dependencies);
            }
            else
            {
                Debug.Log($"对象{each.name}不是一个预制体！当前不支持此类型的对象！", each);
            }
        }

        /// <summary>
        /// 复制资产时，忽略路径中带有以下字符串的资产
        /// </summary>
        private static readonly List<string> CollectIgnoreFolderList = new()
        {
            "Font/",
            "Fonts/",
            "Assets/TextMesh Pro",
            "Packages/com.unity.textmeshpro",
            "Resources/unity_builtin_extra",
            "Packages/com.unity.ugui/Editor Resources/Gizmos/"
        };

        /// <summary>
        ///  处理依赖资产
        /// </summary>  
        private static void DealDependencies(GameObject go, Object[] dependencies)
        {
            //处理贴图资产
            DealTextureAsset(go, dependencies);

            //其余尚未实现
        }

        /// <summary>
        ///  资产对应字典的临时文件路径
        /// </summary>
        private static string TempPath => Path.Combine(Application.temporaryCachePath, "collectandcopyasset.txt");

        /// <summary>
        ///  处理贴图资产
        /// </summary>
        private static void DealTextureAsset(GameObject go, Object[] dependencies)
        {
            //筛选出所有的贴图资产
            var textures = dependencies.Where(d => d is Texture2D).ToArray();

            // 过滤掉路径中包含有忽略文件夹的贴图
            textures = textures.Where(t =>
                !CollectIgnoreFolderList.Any(i =>
                    AssetDatabase.GetAssetPath(t).Contains(i, StringComparison.CurrentCultureIgnoreCase))).ToArray();

            // 目标路径 = 在Prefabs文件夹的上一级目录下的Textures文件夹 
            CreateFolder(go);
            var targetPath = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(AssetDatabase.GetAssetPath(go)))!,
                "Textures");

            // 声明一个资产对应字典
            var dict = new Dictionary<string, string>();

            // 复制资产到目标路径
            foreach (var texture in textures)
            {
                var assetPath = AssetDatabase.GetAssetPath(texture);
                var targetFilePath = Path.Combine(targetPath, Path.GetFileName(assetPath));

                //如果路径一致，则忽略这个贴图
                if (Path.GetFullPath(assetPath) == Path.GetFullPath(targetFilePath)) continue;

                AssetDatabase.CopyAsset(assetPath, targetFilePath);
                Debug.Log($"复制贴图资产：{assetPath} 到 {targetFilePath}");
                dict.Add(assetPath, targetFilePath);
            }

            // 存储资产对应字典到临时文件
            File.WriteAllText(TempPath, JsonConvert.SerializeObject(dict));

            //刷新资源
            AssetDatabase.Refresh();

            //读取临时文件中的资产对应字典
            dict = JsonConvert.DeserializeObject<Dictionary<string, string>>
                (File.ReadAllText(TempPath));

            //打开预制体文件夹，替换UUID
            foreach (var pair in dict)
            {
                ReplaceUuidInPrefab(go, pair.Key, pair.Value);
            }
        }

        /// <summary>
        /// 创建目标路径
        /// </summary>
        private static void CreateFolder(GameObject go)
        {
            var goPath = GetAbsolutePath(go);
            var goFolder = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(goPath))!, "Textures");
            if (!Directory.Exists(goFolder))
            {
                Directory.CreateDirectory(goFolder);
                AssetDatabase.Refresh();
            }
        }

        /// <summary>
        ///  替换预制体中的UUID
        /// </summary>
        private static void ReplaceUuidInPrefab(GameObject go, string originPath,
            string targetPath)
        {
            //获取go的绝对路径
            var goAbsolutePath = GetAbsolutePath(go);

            //读取go的文本
            var goText = File.ReadAllText(goAbsolutePath);

            //获取 originPath 的资产的UUID
            var originUuid = AssetDatabase.AssetPathToGUID(originPath);

            // 获取 targetPath 的资产的UUID
            var targetUuid = AssetDatabase.AssetPathToGUID(targetPath);

            //替换文本
            goText = goText.Replace(originUuid, targetUuid);

            //写回文本
            File.WriteAllText(goAbsolutePath, goText);

            //刷新资产
            AssetDatabase.Refresh();
        }


        /// <summary>
        ///  获取绝对路径
        /// </summary>
        private static string GetAbsolutePath(GameObject asset)
        {
            //获取go的资产路径
            var goPath = AssetDatabase.GetAssetPath(asset);
            if (goPath.StartsWith("Assets/"))
            {
                //如果是Assets文件夹下的路径，则直接返回
                return Path.Combine(Application.dataPath, "..", goPath);
            }

            var info = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(goPath);
            var split = goPath.Split(info.assetPath)[1].Replace('/', '\\').TrimStart('\\');
            var path = Path.Combine(info.resolvedPath, split);
            return path;
        }
    }
}

#endif